//
//  SKYNetwork.m
//  SkyonSDK
//
//  Created by 张二帅 on 2018/5/12.
//  Copyright © 2018年 Skyon. All rights reserved.
//

#import "SKYNetwork.h"
#import "SKYNetworkSection.h"
#import <UIKit/UIKit.h>
#import "SKYInfoServer.h"

@interface SKYNetwork (SKYRequest)
- (NSMutableURLRequest *)POSTURLString:(NSString *)URLString packets:(NSArray *)packets;
- (NSMutableURLRequest *)GETURLString:(NSString *)URLString;
@end

/**
 请求方式
 
 - SKYHTTPMethod_GET: get请求
 - SKYHTTPMethod_POST: post请求
 */
typedef NS_ENUM(NSInteger,SKYHTTPMethod) {
    SKYHTTPMethod_GET,
    SKYHTTPMethod_POST
};

@interface SKYNetwork()
/** 请求方式 */
@property (nonatomic) SKYHTTPMethod requestMethod;
/** 请求头 */
@property (nonatomic, strong) NSMutableDictionary *requestHeaders;
/** 请求cookies */
@property (nonatomic, strong) NSMutableArray *requestCookies;
/** baseUrl */
@property (nonatomic, strong) NSURL *baseUrl;
@end

@implementation SKYNetwork

- (instancetype)initWithBaseUrl:(nullable NSURL *)url {
    if (self = [super init]) {
        _requestHeaders = [NSMutableDictionary dictionary];
        _requestCookies = [NSMutableArray array];
        _timeoutTime = 60.0f;
        if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
            url = [url URLByAppendingPathComponent:@""];
        }
        _baseUrl = url;
    }
    return self;
}

+ (instancetype)config {
    SKYNetwork *network = [[SKYNetwork alloc] initWithBaseUrl:nil];
    return network;
}

- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;{
    [self.requestHeaders setValue:value forKey:field];
}

- (void)addRequestCookie:(NSHTTPCookie *)cookie;{
    if (cookie) {
        [self.requestCookies addObject:cookie];
    }
}

- (void)POSTURLString:(NSString *)URLString packets:(NSArray *)packets completionHandler:(void(^)(NSData *data,NSError *error))completionHandler;{
    [self URLRequest:[self POSTURLString:URLString packets:packets] completionHandler:completionHandler];
}

- (void)GETURLString:(NSString *)URLString completionHandler:(void(^)(NSData *data,NSError *error))completionHandler;{
    [self URLRequest:[self GETURLString:URLString] completionHandler:completionHandler];
}

- (void)URLRequest:(NSMutableURLRequest *)request completionHandler:(void (^)(NSData * _Nullable data, NSError * _Nonnull error))completionHandler {
    if (@available(iOS 7.0, *)) {
        [[SKYNetworkSection section] request:request completionHandler:^(NSHTTPURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable error) {
            if (completionHandler) {
                completionHandler(data,error);
            }
        }];
    } else {
        [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
            if (completionHandler) {
                completionHandler(data,connectionError);
            }
        }];
    }
}


@end


/**
 序列化报文 ‘|~|’ 格式参数

 @param packets 参数列表
 @return 序列化后字符串
 */
NSString *SKYSerializationFromPackets(NSArray *packets) {
    NSString *packetMarkString = @"|~|";
    NSString *packetString = [packets componentsJoinedByString:packetMarkString];
    return [NSString stringWithFormat:@"%@%@-",packetString,packetMarkString];
}

/**
 构建报文为‘|~|’请求体

 @param packets 参数列表
 @return 请求体二进制数据
 */
NSData *SKYRequestBodyWithPackets(NSArray *packets) {
    NSString *serializationString = SKYSerializationFromPackets(packets);
    if ([SKYInfoServer sharedInstance].logEnabled) {
        NSLog(@"%@",serializationString);
    }
    return [serializationString dataUsingEncoding:NSUTF8StringEncoding];
}

@implementation SKYNetwork (SKYRequest)

- (NSMutableURLRequest *)POSTURLString:(NSString *)URLString packets:(nullable NSArray *)packets {
    return [self requestMethod:@"POST" URLString:URLString packets:packets];
}

- (NSMutableURLRequest *)GETURLString:(NSString *)URLString {
    return [self requestMethod:@"GET" URLString:URLString];
}

- (NSMutableURLRequest *)requestMethod:(NSString *)method URLString:(NSString *)URLString packets:(nullable NSArray *)packets {
    NSMutableURLRequest *request = [self requestMethod:method URLString:URLString];
    request.HTTPBody = (packets == nil || packets.count == 0) ? nil : SKYRequestBodyWithPackets(packets);
    return request;
}

- (NSMutableURLRequest *)requestMethod:(NSString *)method URLString:(NSString *)URLString {
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:URLString relativeToURL:self.baseUrl]];
    request.HTTPMethod = method;
    request.timeoutInterval = self.timeoutTime;
    [self buildHeaderRequest:request];
    return request;
}

- (void)buildHeaderRequest:(NSMutableURLRequest *)request {
//    [self setHTTPHeaderAcceptLanguage];
//    [self setHTTPHeaderUserAgent];
//    [self setHTTPHeaderCookies];
    [self.requestHeaders enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        if (![request valueForHTTPHeaderField:key]) {
            [request setValue:obj forHTTPHeaderField:key];
        }
    }];
}

- (void)setHTTPHeaderAcceptLanguage {
    // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
    NSMutableArray *acceptLanguagesComponents = [NSMutableArray array];
    [[NSLocale preferredLanguages] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        float q = 1.0f - (idx * 0.1f);
        [acceptLanguagesComponents addObject:[NSString stringWithFormat:@"%@;q=%0.1g", obj, q]];
        *stop = q <= 0.5f;
    }];
    [self setValue:[acceptLanguagesComponents componentsJoinedByString:@", "] forHTTPHeaderField:@"Accept-Language"];
}

- (void)setHTTPHeaderUserAgent {
    NSString *userAgent = nil;
    [[UIDevice currentDevice] model];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
#if TARGET_OS_IOS
    // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
    userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
#elif TARGET_OS_WATCH
    // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
    userAgent = [NSString stringWithFormat:@"%@/%@ (%@; watchOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[WKInterfaceDevice currentDevice] model], [[WKInterfaceDevice currentDevice] systemVersion], [[WKInterfaceDevice currentDevice] screenScale]];
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
    userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]];
#endif
#pragma clang diagnostic pop
    if (userAgent) {
        if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) {
            NSMutableString *mutableUserAgent = [userAgent mutableCopy];
            if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) {
                userAgent = mutableUserAgent;
            }
        }
        [self setValue:userAgent forHTTPHeaderField:@"User-Agent"];
    }
}

- (void)setHTTPHeaderCookies {
    if (self.requestCookies.count > 0) {
        NSString *cookieHeader = nil;
        for (NSHTTPCookie *cookie in self.requestCookies) {
            if (!cookieHeader) {
                cookieHeader = [NSString stringWithFormat: @"%@=%@",[cookie name],[cookie value]];
            } else {
                cookieHeader = [NSString stringWithFormat: @"%@; %@=%@",cookieHeader,[cookie name],[cookie value]];
            }
        }
        if (cookieHeader) {
            [self setValue:cookieHeader forHTTPHeaderField:@"Cookie"];
        }
    }
}


@end

